import { expect } from '@jest/globals';
import * as fse from 'fs-extra';
import path from 'path';

import { getJson5Obj } from '../../../../src/utils/json-util';
import { addDependency, addRouterMap, hasCommonElements, initExecuteCommand, isEqual, runHvigorAsync } from '../../common/common';
import {
  AbilityType,
  APIType,
  APIVersion,
  CaseLevel,
  LanguageType,
  ModuleTemplateType,
  RuntimeOSType,
  SDKType,
} from '../../plugins/project-builder/models/constants';
import { TestCaseBuilder } from '../../plugins/task-builder/task-case-builder';
import { ProjectBuildOption, TestCaseFun } from '../../plugins/task-builder/test-case';
import { TestTaskOptionBuilder } from '../../plugins/task-builder/test-task-option';

const projectBuilderOption: ProjectBuildOption = {
  template: {
    sdk: SDKType.Single,
    runtimeOS: RuntimeOSType.HarmonyOS,
    apiVersion: APIVersion.API11,
    apiType: APIType.STAGE,
    language: LanguageType.ArkTs,
    abilityType: AbilityType.Application,
    entryTemplateType: ModuleTemplateType.EmptyAbility,
  },
  modulesOption: {
    [ModuleTemplateType.StaticLibraryWithC]: 1,
  },
};

function deepEqual(obj1: any, obj2: any): boolean {
  if (obj1 === obj2) return true;

  if (typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 === null || obj2 === null) {
    return false;
  }

  const keys1 = Object.keys(obj1);
  const keys2 = Object.keys(obj2);

  if (keys1.length !== keys2.length) return false;

  for (const key of keys1) {
    if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) {
      return false;
    }
  }

  return true;
}

const testFun: TestCaseFun = async (project, taskConfig, record) => {
  const commandsHap = initExecuteCommand({
    sync: true,
    mode: 'module',
    module: 'entry@default',
    product: 'default',
    buildMode: 'debug',
    tasks: 'assembleHap',
  });

  // entry添加routerMap
  const entryRootPath = project.getModule('entry').moduleRootPath();
  await addRouterMap(entryRootPath, {
    name: 'DynamicPageB1',
    pageSourceFile: 'src/main/ets/pages/Index.ets',
    buildFunction: '',
  });
  await addDependency(entryRootPath, { staticNativeCLibrary: 'file:../staticNativeCLibrary' });

  // har添加routermap
  const staticNativeCLibraryRootPath = project.getModule('staticNativeCLibrary').moduleRootPath();
  await addRouterMap(staticNativeCLibraryRootPath, {
    name: 'DynamicPageB2',
    pageSourceFile: 'src/main/ets/components/mainpage/MainPage.ets',
    buildFunction: '',
  });

  // 配置ohmurl
  const projectBuildProfileJsonPath = path.resolve(project.projectRootPath(), 'build-profile.json5');
  const projectBuildProfileJsonObj = getJson5Obj(projectBuildProfileJsonPath);
  Object.assign(projectBuildProfileJsonObj.app.products[0], {
    buildOption: {
      strictMode: {
        useNormalizedOHMUrl: true,
      },
    },
  });
  await fse.writeJson(projectBuildProfileJsonPath, projectBuildProfileJsonObj, { spaces: 2 });

  const result = await runHvigorAsync(project.projectRootPath(), commandsHap);

  // processRouterMap任務正常完成
  expect(result.stdout).toContain('Finished :entry:default@ProcessRouterMap');

  // 检查loader.json中compileEntry
  const loaderJsonObj = getJson5Obj(path.resolve(entryRootPath, 'build/default/intermediates/loader/default/loader.json'));
  const compileEntry = [
    path.resolve(entryRootPath, 'src/main/ets/pages/Index.ets'),
    path.resolve(staticNativeCLibraryRootPath, 'src/main/ets/components/mainpage/MainPage.ets'),
  ];
  expect(hasCommonElements(loaderJsonObj.compileEntry, compileEntry)).toBe(true);

  // 检查hap包产物routerMap配置 包括entry+har
  const intermediatesRouterMapJsonObj = getJson5Obj(
    path.resolve(entryRootPath, 'build/default/intermediates/res/default/resources/base/profile/routerMap.json'),
  );

  const case01 = {
    routerMap: [
      {
        name: 'DynamicPageB1',
        pageSourceFile: 'src/main/ets/pages/Index.ets',
        buildFunction: '',
        ohmurl: '@normalized:N&&&entry/src/main/ets/pages/Index&',
        bundleName: 'com.example.myapplication',
        moduleName: 'entry',
      },
      {
        name: 'DynamicPageB2',
        pageSourceFile: 'src/main/ets/components/mainpage/MainPage.ets',
        buildFunction: '',
        ohmurl: '@normalized:N&&&staticNativeCLibrary/src/main/ets/components/mainpage/MainPage&1.0.0',
        bundleName: 'com.example.myapplication',
        moduleName: 'entry',
        packageName: 'staticNativeCLibrary'
      },
    ],
  }

  expect(deepEqual(intermediatesRouterMapJsonObj, case01)).toBe(true);

  // 检查loader.json的dynamicImportLibInfo
  const intermediatesPkgContextInfoJsonObj = getJson5Obj(path.resolve(entryRootPath, 'build/default/intermediates/loader/default/pkgContextInfo.json'));
  const case02 = {
    staticNativeCLibrary: {
      packageName: 'staticNativeCLibrary',
      bundleName: '',
      moduleName: '',
      version: '1.0.0',
      entryPath: 'Index.ets',
      isSO: false,
      dependencyAlias: '',
    },
    'liblibrary.so': {
      packageName: 'liblibrary.so',
      bundleName: '',
      moduleName: '',
      version: '',
      entryPath: 'index',
      isSO: true,
      dependencyAlias: '',
    },
    '@ohos/hypium': {
      packageName: '@ohos/hypium',
      bundleName: '',
      moduleName: '',
      version: '1.0.11',
      entryPath: 'index.js',
      isSO: false,
      dependencyAlias: '',
    },
    entry: {
      packageName: 'entry',
      bundleName: '',
      moduleName: '',
      version: '',
      entryPath: 'src/main/',
      isSO: false,
      dependencyAlias: '',
    },
  };

  expect(deepEqual(intermediatesPkgContextInfoJsonObj, case02)).toBe(true);
  expect(Object.keys(loaderJsonObj.dynamicImportLibInfo).length === 0).toBe(true);
};

TestCaseBuilder.builder()
  .caseName('OPENLAB_AIDE_ZOS_BUILD_DYNAMIC_ROUTE_ohmurl_016')
  .description(
    '1. 创建C++工程；\n' +
      '2. 新增Native-Shared Library\n' +
      '3.在hap和hsp的\\src\\main\\resources\\base\\profile下新增routerMap.json文件，\n' +
      '4.在hap和hsp的module.json5中添加标签"routerMap":"$profile:routerMap"，\n' +
      '5. hap模块oh-package.json中配置包依赖 "library":"file:../library"\n' +
      '6.工程级的build-profile.json5中的product-default下配置        "buildOption": {\n' +
      '          "strictMode": {\n' +
      '            "useNormalizedOHMUrl": true\n' +
      '          }\n' +
      '        }\n' +
      '7.构建hap',
  )
  .projectBuilderOption(projectBuilderOption)
  .taskConfig(TestTaskOptionBuilder.builder().caseLevel(CaseLevel.L1).build())
  .testFun(testFun)
  .load();
